Next.js Route Handlers kullanarak nasıl güçlü API uç noktaları oluşturacağınızı öğrenin. Bu rehber, temel kurulumdan ileri düzey tekniklere, pratik örnekler ve en iyi uygulamalarla her şeyi kapsar.
Next.js Route Handlers: API Uç Noktası Oluşturma İçin Kapsamlı Bir Rehber
Next.js, sunucu taraflı işleme (server-side rendering), statik site oluşturma (static site generation) ve şimdi de Route Handlers gibi güçlü özellikleriyle web uygulamaları oluşturma şeklimizde devrim yarattı. Route Handlers, doğrudan Next.js uygulamanız içinde API uç noktaları oluşturmanın esnek ve verimli bir yolunu sunar. Bu kılavuz, Route Handlers kavramını, faydalarını ve sağlam API'ler oluşturmak için bunları nasıl etkili bir şekilde kullanacağınızı ele almaktadır.
Next.js Route Handlers Nedir?
Route Handlers, bir Next.js projesinin app
dizini içinde tanımlanan ve gelen HTTP isteklerini işleyen fonksiyonlardır. Eski pages/api
yaklaşımının (API Rotalarını kullanan) aksine, Route Handlers, React bileşenlerinizin yanı sıra API uç noktalarını tanımlamak için daha modern ve esnek bir yol sunar. Bunlar esasen edge'de veya seçtiğiniz sunucu ortamında yürütülen sunucusuz fonksiyonlardır.
Route Handlers'ı, istekleri işlemekten, veritabanlarıyla etkileşimde bulunmaktan ve yanıtları döndürmekten sorumlu olan Next.js uygulamanızın backend mantığı olarak düşünebilirsiniz.
Route Handlers Kullanmanın Faydaları
- Birlikte Konumlandırma (Colocation): Route Handlers,
app
dizini içinde doğrudan React bileşenlerinizin yanında yer alır, bu da daha iyi organizasyon ve kod sürdürülebilirliğini teşvik eder. - TypeScript Desteği: Dahili TypeScript desteği, tür güvenliği ve geliştirilmiş geliştirici deneyimi sağlar.
- Middleware Entegrasyonu: Kimlik doğrulama, yetkilendirme ve istek doğrulama gibi görevler için ara yazılımları (middleware) kolayca entegre edin.
- Akış (Streaming) Desteği: Route Handlers veri akışı yapabilir, bu da yanıtları artımlı olarak göndermenizi sağlar; bu, büyük veri setleri veya uzun süren işlemler için faydalıdır.
- Edge Fonksiyonları: Küresel CDN'lerden yararlanarak kullanıcılarınıza daha yakın, düşük gecikmeli yanıtlar için Route Handlers'ı Edge Fonksiyonları olarak dağıtın.
- Basitleştirilmiş API Tasarımı: Route Handlers, istekleri ve yanıtları işlemek için temiz ve sezgisel bir API sağlar.
- Server Actions Entegrasyonu: Server Actions ile sıkı entegrasyon, istemci tarafı bileşenleriniz ve sunucu tarafı mantığınız arasında sorunsuz iletişim sağlar.
Next.js Projenizi Kurma
Route Handlers'a dalmadan önce, app
dizini ile kurulmuş bir Next.js projeniz olduğundan emin olun. Yeni bir proje başlatıyorsanız, aşağıdaki komutu kullanın:
npx create-next-app@latest my-nextjs-app
Kurulum işlemi sırasında yeni yönlendirme sistemini etkinleştirmek için app
dizinini seçin.
İlk Route Handler'ınızı Oluşturma
JSON yanıtı döndüren basit bir API uç noktası oluşturalım. app
dizini içinde, örneğin, /app/api/hello
gibi yeni bir dizin oluşturun. Bu dizinin içine route.ts
(veya TypeScript kullanmıyorsanız route.js
) adında bir dosya oluşturun.
İşte ilk Route Handler'ınız için kod:
// app/api/hello/route.ts
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
return NextResponse.json({ message: 'Next.js Route Handlers\'dan Merhaba!' });
}
Açıklama:
import { NextResponse } from 'next/server';
: API yanıtları oluşturmak için kullanılanNextResponse
nesnesini içe aktarır.export async function GET(request: Request) { ... }
:/api/hello
uç noktasına gelen GET isteklerini işleyen asenkron bir fonksiyon tanımlar.request
parametresi, gelen istek nesnesine erişim sağlar.return NextResponse.json({ message: 'Next.js Route Handlers\'dan Merhaba!' });
: Bir mesaj içeren bir JSON yanıtı oluşturur ve bunuNextResponse.json()
kullanarak döndürür.
Şimdi, tarayıcınızda /api/hello
adresine giderek veya curl
ya da Postman
gibi bir araç kullanarak bu uç noktasına erişebilirsiniz.
Farklı HTTP Metotlarını İşleme
Route Handlers, GET, POST, PUT, DELETE, PATCH ve OPTIONS gibi çeşitli HTTP metotlarını destekler. Aynı route.ts
dosyası içinde her metot için ayrı fonksiyonlar tanımlayabilirsiniz.
// app/api/users/route.ts
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
// Veritabanından tüm kullanıcıları getirme mantığı
const users = [{ id: 1, name: 'John Doe' }, { id: 2, name: 'Jane Smith' }]; // Örnek veri
return NextResponse.json(users);
}
export async function POST(request: Request) {
const data = await request.json(); // İstek gövdesini JSON olarak ayrıştır
// 'data' kullanarak veritabanında yeni bir kullanıcı oluşturma mantığı
const newUser = { id: 3, name: data.name, email: data.email }; // Örnek
return NextResponse.json(newUser, { status: 201 }); // Yeni kullanıcıyı 201 Oluşturuldu durum koduyla döndür
}
Açıklama:
GET
fonksiyonu bir kullanıcı listesi alır (burada simüle edilmiştir) ve bunları bir JSON yanıtı olarak döndürür.POST
fonksiyonu istek gövdesini JSON olarak ayrıştırır, yeni bir kullanıcı oluşturur (simüle edilmiş) ve yeni kullanıcıyı 201 Oluşturuldu durum koduyla döndürür.
İstek Verilerine Erişme
request
nesnesi, başlıklar (headers), sorgu parametreleri (query parameters) ve istek gövdesi (request body) dahil olmak üzere gelen istekle ilgili çeşitli bilgilere erişim sağlar.
Başlıklar (Headers)
request.headers
özelliğini kullanarak istek başlıklarına erişebilirsiniz:
export async function GET(request: Request) {
const userAgent = request.headers.get('user-agent');
console.log('User Agent:', userAgent);
return NextResponse.json({ userAgent });
}
Sorgu Parametreleri (Query Parameters)
Sorgu parametrelerine erişmek için URL
yapıcısını kullanabilirsiniz:
export async function GET(request: Request) {
const url = new URL(request.url);
const searchParams = new URLSearchParams(url.search);
const id = searchParams.get('id');
console.log('ID:', id);
return NextResponse.json({ id });
}
İstek Gövdesi (Request Body)
POST, PUT ve PATCH istekleri için, içerik türüne bağlı olarak request.json()
veya request.text()
metotlarını kullanarak istek gövdesine erişebilirsiniz.
export async function POST(request: Request) {
const data = await request.json();
console.log('Data:', data);
return NextResponse.json({ receivedData: data });
}
Yanıtları Döndürme
NextResponse
nesnesi API yanıtları oluşturmak için kullanılır. Başlıkları, durum kodlarını ve yanıt gövdelerini ayarlamak için birkaç metot sağlar.
JSON Yanıtları
JSON yanıtları döndürmek için NextResponse.json()
metodunu kullanın:
return NextResponse.json({ message: 'Success!', data: { name: 'John Doe' } }, { status: 200 });
Metin Yanıtları
Düz metin yanıtları döndürmek için new Response()
yapıcısını kullanın:
return new Response('Hello, world!', { status: 200, headers: { 'Content-Type': 'text/plain' } });
Yönlendirmeler
Kullanıcıları farklı bir URL'ye yönlendirmek için NextResponse.redirect()
kullanın:
import { redirect } from 'next/navigation';
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
return NextResponse.redirect(new URL('/new-location', request.url));
}
Başlıkları Ayarlama
NextResponse.json()
veya new Response()
içindeki headers
seçeneğini kullanarak özel başlıklar ayarlayabilirsiniz:
return NextResponse.json({ message: 'Success!' }, { status: 200, headers: { 'Cache-Control': 'no-cache' } });
Middleware Entegrasyonu
Middleware, bir istek Route Handler'ınız tarafından işlenmeden önce kod çalıştırmanıza olanak tanır. Bu, kimlik doğrulama, yetkilendirme, günlük kaydı (logging) ve diğer kesişen ilgiler (cross-cutting concerns) için kullanışlıdır.
Middleware oluşturmak için, app
dizininde veya herhangi bir alt dizinde middleware.ts
(veya middleware.js
) adında bir dosya oluşturun. Middleware, o dizin ve alt dizinlerindeki tüm rotalara uygulanacaktır.
// app/middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const token = request.cookies.get('auth-token');
if (!token) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ['/protected/:path*'], // Bu middleware'i /protected/ ile başlayan yollara uygula
};
Açıklama:
middleware
fonksiyonu, istek çerezlerinde bir kimlik doğrulama jetonu (token) olup olmadığını kontrol eder.- Jeton yoksa, kullanıcıyı giriş sayfasına yönlendirir.
- Aksi takdirde, isteğin Route Handler'a devam etmesine izin verir.
config
nesnesi, bu middleware'in yalnızca/protected/
ile başlayan rotalara uygulanması gerektiğini belirtir.
Hata Yönetimi
Sağlam API'ler oluşturmak için uygun hata yönetimi çok önemlidir. İstisnaları işlemek ve uygun hata yanıtları döndürmek için try...catch
bloklarını kullanabilirsiniz.
export async function GET(request: Request) {
try {
// Bir hata simüle et
throw new Error('Something went wrong!');
} catch (error: any) {
console.error('Error:', error);
return NextResponse.json({ error: error.message }, { status: 500 });
}
}
Açıklama:
try...catch
bloğu, Route Handler içinde meydana gelen tüm istisnaları yakalar.catch
bloğunda hata günlüğe kaydedilir ve 500 Dahili Sunucu Hatası durum koduyla bir hata yanıtı döndürülür.
Akış (Streaming) Yanıtları
Route Handlers, akış yanıtlarını destekler, bu da verileri istemciye artımlı olarak göndermenize olanak tanır. Bu, özellikle büyük veri setleri veya uzun süren işlemler için kullanışlıdır.
import { Readable } from 'stream';
import { NextResponse } from 'next/server';
async function* generateData() {
for (let i = 0; i < 10; i++) {
await new Promise(resolve => setTimeout(resolve, 500)); // Gecikmeyi simüle et
yield `Data chunk ${i}\n`;
}
}
export async function GET(request: Request) {
const readableStream = Readable.from(generateData());
return new Response(readableStream, {
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
});
}
Açıklama:
generateData
fonksiyonu, bir gecikmeyle veri parçaları üreten (yield) asenkron bir jeneratördür.Readable.from()
metodu, jeneratörden okunabilir bir akış oluşturur.Response
nesnesi, gövde olarak okunabilir akışla oluşturulur veContent-Type
başlığıtext/plain
olarak ayarlanır.
Kimlik Doğrulama ve Yetkilendirme
API uç noktalarınızı güvence altına almak çok önemlidir. Kimlik doğrulama ve yetkilendirmeyi middleware kullanarak veya doğrudan Route Handler'larınız içinde uygulayabilirsiniz.
Kimlik Doğrulama (Authentication)
Kimlik doğrulama, isteği yapan kullanıcının kimliğini doğrular. Yaygın kimlik doğrulama yöntemleri şunları içerir:
- JWT (JSON Web Jetonları): Başarılı giriş üzerine bir jeton oluşturun ve sonraki isteklerde bunu doğrulayın.
- Oturum Tabanlı Kimlik Doğrulama: Oturum tanımlayıcılarını saklamak için çerezleri kullanın ve her istekte bunları doğrulayın.
- OAuth: Kimlik doğrulamayı Google veya Facebook gibi üçüncü taraf bir sağlayıcıya devredin.
İşte middleware kullanarak JWT kimlik doğrulamasına bir örnek:
// app/middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import jwt from 'jsonwebtoken';
const secret = process.env.JWT_SECRET || 'your-secret-key'; // Güçlü, rastgele oluşturulmuş bir gizli anahtarla değiştirin
export function middleware(request: NextRequest) {
const token = request.cookies.get('auth-token')?.value;
if (!token) {
return NextResponse.json({ message: 'Authentication required' }, { status: 401 });
}
try {
jwt.verify(token, secret);
return NextResponse.next();
} catch (error) {
return NextResponse.json({ message: 'Invalid token' }, { status: 401 });
}
}
export const config = {
matcher: ['/api/protected/:path*'],
};
Yetkilendirme (Authorization)
Yetkilendirme, bir kullanıcının hangi kaynaklara erişmesine izin verildiğini belirler. Bu genellikle rollere veya izinlere dayanır.
Yetkilendirmeyi, Route Handler'larınız içinde kullanıcının rollerini veya izinlerini kontrol ederek ve erişimleri yoksa bir hata döndürerek uygulayabilirsiniz.
// app/api/admin/route.ts
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
// Jeton veya oturumdan kullanıcının rolünü alan bir fonksiyonunuz olduğunu varsayın
const userRole = await getUserRole(request);
if (userRole !== 'admin') {
return NextResponse.json({ message: 'Unauthorized' }, { status: 403 });
}
// Yönetici verilerini getirme mantığı
const adminData = { message: 'Admin data' };
return NextResponse.json(adminData);
}
async function getUserRole(request: Request): Promise {
// İstenen kullanıcının rolünü çıkarmak için gerçek mantığınızla değiştirin
// Bu, bir JWT jetonunu doğrulamayı veya bir oturumu kontrol etmeyi içerebilir
return 'admin'; // Örnek: gösterim için sabit kodlanmış rol
}
Route Handlers'ı Dağıtma
Route Handlers, seçtiğiniz barındırma sağlayıcısında sunucusuz fonksiyonlar olarak dağıtılır. Next.js, Vercel, Netlify, AWS ve daha fazlası dahil olmak üzere çeşitli dağıtım platformlarını destekler.
Vercel için dağıtım, Git deponuzu Vercel'e bağlamak ve kodunuzu göndermek kadar basittir. Vercel, Next.js projenizi otomatik olarak algılar ve Route Handler'larınızı sunucusuz fonksiyonlar olarak dağıtır.
İleri Düzey Teknikler
Edge Fonksiyonları
Route Handlers, kullanıcılarınıza daha yakın olan bir CDN'nin ucunda (edge) yürütülen Edge Fonksiyonları olarak dağıtılabilir. Bu, gecikmeyi önemli ölçüde azaltabilir ve performansı artırabilir.
Bir Route Handler'ı Edge Fonksiyonu olarak dağıtmak için, route.ts
dosyanıza edge
çalışma zamanını ekleyin:
export const runtime = 'edge';
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
return NextResponse.json({ message: 'Hello from the Edge!' });
}
Server Actions
Server Actions, sunucu tarafı kodunu doğrudan React bileşenlerinizden çalıştırmanıza olanak tanır. Route Handlers ve Server Actions sorunsuz bir şekilde birlikte çalışarak karmaşık uygulamaları kolaylıkla oluşturmanıza olanak tanır.
İşte bir Route Handler'ı çağırmak için bir Server Action kullanma örneği:
// app/components/MyComponent.tsx
'use client';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
async function handleSubmit(data: FormData) {
'use server';
const name = data.get('name');
const email = data.get('email');
const response = await fetch('/api/users', {
method: 'POST',
body: JSON.stringify({ name, email }),
});
if (response.ok) {
router.refresh(); // Değişiklikleri yansıtmak için sayfayı yenile
}
}
export default function MyComponent() {
const router = useRouter();
return (
);
}
Önbellekleme (Caching)
Önbellekleme, API uç noktalarınızın performansını önemli ölçüde artırabilir. Yanıtlarınızın tarayıcılar ve CDN'ler tarafından nasıl önbelleğe alınacağını kontrol etmek için Cache-Control
başlığını kullanabilirsiniz.
return NextResponse.json({ message: 'Success!' }, { status: 200, headers: { 'Cache-Control': 'public, max-age=3600' } });
Bu örnek, Cache-Control
başlığını public, max-age=3600
olarak ayarlar, bu da tarayıcılara ve CDN'lere yanıtı bir saat boyunca önbelleğe almalarını söyler.
En İyi Uygulamalar
- TypeScript Kullanın: Kod kalitesini artırmak ve hataları önlemek için TypeScript'in tür güvenliğinden yararlanın.
- İstekleri Doğrulayın: Veri bütünlüğünü sağlamak ve kötü niyetli girdileri önlemek için gelen istekleri doğrulayın.
- Hataları Zarifçe Yönetin: İstemcilere bilgilendirici hata mesajları sağlamak için uygun hata yönetimi uygulayın.
- Uç Noktalarınızı Güvence Altına Alın: API uç noktalarınızı korumak için kimlik doğrulama ve yetkilendirme uygulayın.
- Middleware Kullanın: Kimlik doğrulama, günlük kaydı ve istek doğrulama gibi kesişen ilgiler için middleware kullanın.
- Yanıtları Önbelleğe Alın: API uç noktalarınızın performansını artırmak için önbellekleme kullanın.
- API'larınızı İzleyin: Sorunları hızlı bir şekilde belirlemek ve çözmek için API'larınızı izleyin.
- API'larınızı Belgeleyin: Diğer geliştiricilerin kullanımını kolaylaştırmak için API'larınızı belgeleyin. API dokümantasyonu için Swagger/OpenAPI gibi araçları kullanmayı düşünün.
Gerçek Dünya Örnekleri
İşte Route Handlers'ın nasıl kullanılabileceğine dair birkaç gerçek dünya örneği:
- E-ticaret API'si: Ürünleri, siparişleri ve kullanıcıları yönetmek için API uç noktaları oluşturun.
- Sosyal Medya API'si: Tweet göndermek, kullanıcıları takip etmek ve zaman tünellerini almak için API uç noktaları oluşturun.
- İçerik Yönetim Sistemi (CMS) API'si: İçeriği, kullanıcıları ve ayarları yönetmek için API uç noktaları oluşturun.
- Veri Analitiği API'si: Veri toplamak ve analiz etmek için API uç noktaları oluşturun. Örneğin, bir Route Handler farklı web sitelerindeki izleme piksellerinden veri alabilir ve raporlama için bilgileri birleştirebilir.
Uluslararası E-ticaret örneği: Kullanıcının ülkesine göre ürün fiyatlandırmasını getirmek için kullanılan bir Route Handler. Uç nokta, kullanıcının konumunu belirlemek için isteğin coğrafi konumunu (IP adresinden türetilen) kullanabilir ve fiyatları uygun para biriminde döndürebilir. Bu, yerelleştirilmiş bir alışveriş deneyimine katkıda bulunur.
Küresel Kimlik Doğrulama örneği: Dünya çapındaki kullanıcılar için çok faktörlü kimlik doğrulamayı (MFA) uygulayan bir Route Handler. Bu, farklı bölgelerin gizlilik düzenlemelerine ve telekomünikasyon altyapılarına saygı gösterirken SMS kodları göndermeyi veya doğrulayıcı uygulamaları kullanmayı içerebilir.
Çok Dilli İçerik sunumu: Kullanıcının tercih ettiği dilde içerik sunan bir Route Handler. Bu, istekteki `Accept-Language` başlığından belirlenebilir. Bu örnek, uygun UTF-8 kodlamasının ve gerektiğinde sağdan sola dil desteğinin önemini vurgular.
Sonuç
Next.js Route Handlers, doğrudan Next.js uygulamanız içinde API uç noktaları oluşturmanın güçlü ve esnek bir yolunu sunar. Route Handlers'dan yararlanarak, kolaylıkla sağlam API'ler oluşturabilir, backend mantığınızı React bileşenlerinizle birlikte konumlandırabilir ve middleware, akış ve Edge Fonksiyonları gibi özelliklerden faydalanabilirsiniz.
Bu kapsamlı kılavuz, temel kurulumdan ileri düzey tekniklere kadar her şeyi kapsadı. Bu kılavuzda özetlenen en iyi uygulamaları takip ederek, güvenli, performanslı ve sürdürülebilir yüksek kaliteli API'ler oluşturabilirsiniz.